#ifndef __MOD_IPV6__
#define __MOD_IPV6__

#include "decoder.hpp"


// ========================================================================
class IPv6Session : public Session
{
private:
  u_int32_t LKey[4], RKey[4];

public:
  SessionRoot *root[3]; /* 0:TCP, 1:UDP, 2:ICMP6 */

  IPv6Session () {
    this->root[0] = this->root[1] = this->root [2] = NULL;
  }  

  ~IPv6Session ()
  {    
    for (int i = 0; i < 3; i++)
      {
	if (this->root[i])
	  delete this->root [i];
      }
  }

  void setNode (Node * _LNode, Node * _RNode, u_int32_t *_LKey, u_int32_t *_RKey);
  Node * getNode (u_int32_t *key);
  // ToDo:
  // to be implemented reassembler of IPv4 fragments
};

// ========================================================================
class IPv6Filter : public NDecFilter 
{
  friend class IPv6Decoder;

private:
  u_int32_t addr[4], mask[4];

  enum FilterType
    {
      FT_NULL = 0,
      FT_SRC_ADDR,
      FT_DST_ADDR,
    } type;

  void check (NDecResult &res);

public:
  IPv6Filter (FilterType t) : type (t)
  {
    if (this->type == FT_SRC_ADDR ||
	this->type == FT_DST_ADDR)
      this->setResultType (RT_ADDR);
  }
  ~IPv6Filter () {}
  bool setup (string &arg);
};

// ========================================================================
class IPv6Decoder : public Decoder
{
private:
  static const int SSN_TIMEOUT = 600;
  static const bool DEBUG = true;

public:
  static const int ADDR_LEN = 16;
  PTree<Node> nodeTable;
  PTree<Session> ssnTable;

  Record rec;
  IPv6Decoder () {};
  ~IPv6Decoder () {};
  
  Record * decode (Packet & pkt, Record & prev);
  NDecFilter * makeFilter (string &name);
  static void timeoutSession (void * obj);
};

#endif /* __MOD_IPV6__ */
